<?php
// +----------------------------------------------------------------------
// | B5YiiCMF
// +----------------------------------------------------------------------
// | Author: 李恒 <357145480@qq.com>
// +----------------------------------------------------------------------
namespace common\helpers;

use yii\db\Exception;

class TransformApi
{

    /**
     * 获取年龄
     * @param $start
     * @param $end
     * @return bool|int|mixed
     */
    public static function getAge($start, $end = '')
    {
        if (!$start) return false;
        $start = strtotime($start);
        if ($start === false) return false;

        if ($end) {
            $end = strtotime($end);
            if ($end === false) return false;
        } else {
            $end = time();
        }
        if ($end < $start) return false;
        list($y1, $m1, $d1) = explode("-", date("Y-m-d", $start));
        list($y2, $m2, $d2) = explode("-", date("Y-m-d", $end));
        $age = $y2 - $y1;
        if ((int)($m2 . $d2) < (int)($m1 . $d1))
            $age -= 1;
        return $age;
    }

    /**
     * 时间处理
     * @param $timestamp
     * @return false|string
     */
    public static function timeAgo($timestamp)
    {
        $counttime = time() - $timestamp;//相差时间戳
        if ($counttime <= 60) {
            return '刚刚';
        } else if ($counttime < 3600) {
            return intval(($counttime / 60)) . '分钟前';
        } else if ($counttime >= 3600 && $counttime < 3600 * 24) {
            return intval(($counttime / 3600)) . '小时前';
        } else if ($counttime <= 3600 * 24 * 10) {
            return intval(($counttime / (3600 * 24))) . '天前';
        } else {
            return date('Y-m-d', $timestamp);
        }
    }

    /**
     * 容量显示
     * @param $size
     * @return string
     */
    public static function sizeShow($size)
    {
        $size = intval($size);
        if ($size < 0) return '';
        $coin = 'Byte';
        $number = 0;
        $b_size = 1024;
        $kb_size = $b_size * 1024;
        $mb_size = $kb_size * 1024;
        $gb_size = $mb_size * 1024;
        if ($size >= 0 && $size < $b_size) {
            $number = $size;
        } elseif ($size >= $b_size && $size < $mb_size) {
            $number = floor(($size / $b_size) * 100) / 100;
            $coin = 'KB';
        } elseif ($size >= $mb_size && $size < $gb_size) {
            $number = floor(($size / $mb_size) * 100) / 100;
            $coin = 'MB';
        } else {
            $number = floor(($size / $gb_size) * 100) / 100;
            $coin = 'GB';
        }
        return $number . $coin;
    }

    /**
     * 加密函数
     * @param $txt 加密字符串
     * @param string $key 钥匙
     * @return string
     */
    public static function lockUrl($txt, $key = 'ea68d19584c905f2f691263c5c6780e2')
    {
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
        $nh = rand(0, 64);
        $ch = $chars[$nh];
        $mdKey = md5($key . $ch);
        $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
        $txt = base64_encode($txt);
        $tmp = '';
        $i = 0;
        $j = 0;
        $k = 0;
        for ($i = 0; $i < strlen($txt); $i++) {
            $k = $k == strlen($mdKey) ? 0 : $k;
            $j = ($nh + strpos($chars, $txt[$i]) + ord($mdKey[$k++])) % 64;
            $tmp .= $chars[$j];
        }
        return urlencode($ch . $tmp);
    }

    /**
     * 解密函数
     * @param $txt 解密字符串
     * @param string $key 钥匙
     * @return false|string
     */
    public static function unlockUrl($txt, $key = 'ea68d19584c905f2f691263c5c6780e2')
    {
        $txt = urldecode($txt);
        $chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-=+";
        $ch = $txt[0];
        $nh = strpos($chars, $ch);
        $mdKey = md5($key . $ch);
        $mdKey = substr($mdKey, $nh % 8, $nh % 8 + 7);
        $txt = substr($txt, 1);
        $tmp = '';
        $i = 0;
        $j = 0;
        $k = 0;
        for ($i = 0; $i < strlen($txt); $i++) {
            $k = $k == strlen($mdKey) ? 0 : $k;
            $j = strpos($chars, $txt[$i]) - $nh - ord($mdKey[$k++]);
            while ($j < 0) $j += 64;
            $tmp .= $chars[$j];
        }
        return base64_decode($tmp);
    }

    /**
     * 下载文件
     * @param $url 远程文件地址
     * @param $toFile 下载到的目录
     * @return false
     */
    public static function downloadFile($url, $toFile)
    {
        $file = empty($toFile) ? pathinfo($url, PATHINFO_BASENAME) : $toFile;
        $dir = pathinfo($file, PATHINFO_DIRNAME);
        !is_dir($dir) && @mkdir($dir, 0755, true);
        $url = str_replace(" ", "%20", $url);
        $r = fopen($toFile, 'w+');
        if (function_exists('curl_init')) {
            $ch = curl_init();
            curl_setopt($ch, CURLOPT_URL, $url);
            curl_setopt($ch, CURLOPT_RETURNTRANSFER, TRUE);
            $temp = curl_exec($ch);
            if (file_put_contents($file, $temp) && !curl_error($ch)) {
                return $file;
            } else {
                return false;
            }
        } else {
            $opts = array(
                "http" => array(
                    "method" => "GET",
                    "header" => "",
                ));
            $context = stream_context_create($opts);
            if (copy($url, $file, $context)) {
                //$http_response_header
                return $file;
            } else {
                return false;
            }
        }
    }

    /**
     * 解压文件
     * @param $formFile 要解压的文件
     * @param $toFile 解压到那里
     * @return false|string
     */
    public static function uZip($formFile, $toFile)
    {
        //解压缩 php自带的解压类
        $zip = new \ZipArchive;
        //要解压的文件
        $zipfile = $formFile;
        $res = $zip->open($zipfile);
        if ($res !== true) {
            return false;
        }
        //要解压到的目录
        $toDir = $toFile;
        if (!file_exists($toDir)) {
            mkdir($toDir, 755);
        }
        //获取压缩包中的文件数（含目录）
        $docnum = $zip->numFiles;
        $addonname = "";
        //遍历压缩包中的文件
        for ($i = 0; $i < $docnum; $i++) {
            $statInfo = $zip->statIndex($i);
            if ($statInfo['crc'] == 0) {
                if ($i == 0) {
                    if (is_dir($toDir . '/' . substr($statInfo['name'], 0, -1))) {
                        return false;
                    }
                    $addonname = substr($statInfo['name'], 0, -1);
                }
                //新建目录
                mkdir($toDir . '/' . substr($statInfo['name'], 0, -1));
            } else {
                //拷贝文件
                copy('zip://' . $zipfile . '#' . $statInfo['name'], $toDir . '/' . $statInfo['name']);
            }
        }
        return $addonname;
    }

    /**
     * 获取目录下的所有文件
     * @param $dir 路径
     * @return array
     */
    public static function deepScanDir($dir) {
        $fileArr = array ();
        $dirArr = array ();
        $dirArrName = array ();
        $dir = rtrim($dir, '//');
        if (is_dir($dir)) {
            $dirHandle = opendir($dir);
            while (false !== ($fileName = readdir($dirHandle))) {
                $subFile = $dir . DIRECTORY_SEPARATOR . $fileName;
                $dirArrName[] = $fileName;
                if (is_file($subFile)) {
                    $fileArr[] = $subFile;
                }
                elseif (is_dir($subFile) && str_replace('.', '', $fileName) != '') {
                    $dirArr[] = $subFile;
                    $arr = self::deepScanDir($subFile);
                    $dirArr = array_merge($dirArr, $arr['dir']);
                    $fileArr = array_merge($fileArr, $arr['file']);
                }
            }
            closedir($dirHandle);
        }
        return [
            'dir' => $dirArr,
            'file' => $fileArr,
            'dirArrName' => $dirArrName,
        ];
    }

    /**
     * 替换文件内容
     * @param $dir 路径
     * @param $old 查找字符
     * @param $new 替换字符
     */
    public static function fileReplace($dir,array $old,array $new){
        //获取文件
        $dirs = self::deepScanDir($dir);
        //文件字符串替换
        foreach($dirs['file'] as $file){
            $txt = file_get_contents($file);
            $txt = str_replace($old,$new,$txt);
            file_put_contents($file,$txt);
        }
        return true;
    }

    /**
     * 统一事物
     * @param callable $fun
     * @param $result
     * @param $db
     */
    public static function tx(callable $fun, &$result, $db = 'db')
    {
        $tran = \Yii::$app->{$db}->beginTransaction();
        try {
            $result = $fun();
            $tran->commit();
        } catch (Exception $e) {
            $tran->rollBack();
            $result = commonApi::message($e->getMessage(), false);
        }
        return true;
    }

    /**
     * 截取小数点后几位
     * @param $value
     * @param int $digit
     * @return float|int
     */
    public static function decimalPoint($value, $digit = 3)
    {
        $result = intval(bcmul($value, pow(10, $digit))) / pow(10, $digit);
        return $result;
    }

    /**
     * 地址定位
     * @param $add 地址
     * @param $key key
     * @return array
     */
    public static function location($add,$key)
    {
        try {
            $url ="https://restapi.amap.com/v3/geocode/geo?address=$add&output=json&key=$key";
            $result = commonApi::b5curl_get($url);
            $result = json_decode($result,true);
            $data = [];
            if ((int)$result['status']==1){
                if (!empty($result['geocodes'][0])){
                    $location = explode(',',$result['geocodes'][0]['location']);
                    $data = [
                        'address'=>$result['geocodes'][0]['formatted_address'],
                        'country'=>$result['geocodes'][0]['country'],
                        'province'=>$result['geocodes'][0]['province'],
                        'citycode'=>$result['geocodes'][0]['citycode'],
                        'city'=>$result['geocodes'][0]['city'],
                        'district'=>$result['geocodes'][0]['district'],
                        'street'=>$result['geocodes'][0]['street'],
                        'number'=>$result['geocodes'][0]['number'],
                        'adcode'=>$result['geocodes'][0]['adcode'],
                        'long'=>$location[0],
                        'lat'=>$location[1],
                    ];
                    return commonApi::message('ok',true,$data);
                }
            }
            throw new Exception('地址失败');
        }catch (\Exception $e){
            return commonApi::message($e,false);
        }
    }

    /**
     * 批量修改sql
     * @param $table 表名
     * @param $rows 要修改的字段
     * @param $keyPrimaryArrs 标识
     * @param string $id
     * @return string
     */
    public static function batchUpdate($table, $rows, $keyPrimaryArrs,$id='id')
    {
        //查询数据库返回的数据格式
        $newhouse_clicks = $rows;
        //拼接批量更新sql语句
        $sql = "UPDATE $table SET ";
        //合成sql语句
        $one = current($newhouse_clicks);
        foreach ($one as $key => $value) {
            $sql .= "`{$key}` = CASE $id ";
            foreach ($newhouse_clicks as $k => $val) {
                if (strpos($val[$key],'`')!==false){
                    $sql .= "WHEN $keyPrimaryArrs[$k] THEN $val[$key] ";
                }else{
                    $sql .= "WHEN $keyPrimaryArrs[$k] THEN '$val[$key]'";
                }
            }
            $sql .= "END, ";
        }
        //把最后一个,去掉
        $sql = substr($sql, 0, strrpos($sql, ','));
        //合并所有id
        $ids = implode(',', $keyPrimaryArrs);
        //拼接sql
        $sql .= " WHERE $id IN ({$ids})";
        //测试自动提交hah
        return $sql;
    }
}